// 引入axios和定义在node_modules/axios/index.ts文件里的类型声明
import axios, { AxiosInstance, AxiosRequestConfig, AxiosPromise, AxiosResponse } from 'axios';
import { baseURL } from '../config';

// 接口请求地址
const apiBaseUrl = process.env.NODE_ENV === 'production' ? baseURL.pro : baseURL.dev;
 
// 定义接口请求类，用于创建 axios 请求实例
class HttpRequest {
  // 接收接口请求的基本路径
  constructor(public baseUrl: string = apiBaseUrl) { 
    this.baseUrl = baseUrl;
  }
  
  // 调用接口时调用实例的这个方法，返回 AxiosPromise
  public request(options: AxiosRequestConfig): AxiosPromise { 
    // 创建axios实例，它是函数，同时这个函数包含多个属性
    const instance: AxiosInstance = axios.create() 
    // 合并基础路径和每个接口单独传入的配置，比如 url、参数等
    options = this.mergeConfig(options) 
    // 调用 interceptors 方法使拦截器生效
    this.interceptors(instance, options.url) 
    // 返回 AxiosPromise
    return instance(options) 
  }
  
  // 用于添加全局请求和响应拦截
  private interceptors(instance: AxiosInstance, url?: string) { 
    // 请求拦截
    instance.interceptors.request.use((config: AxiosRequestConfig) => {
      // 接口请求的所有配置，可以在 axios.defaults 修改配置
      // config.data = Object.assign({}, config.data, {
      //   // authToken: window.localStorage.getItem('authToken')
      //   authToken: 'FE8730d5-b34d-Aba9-E16D-2B8E9C2Dcf4C'
      // })
      return config
    }, (error) => {
      return Promise.reject(error)
    })

    // 响应拦截
    instance.interceptors.response.use((res: AxiosResponse) => {
      const { data } = res 
      const { code, msg } = data
      if (code !== 200) {
        console.error(msg)
      }
      return data
    }, (error) => { 
      return Promise.reject(error)
    })
  }
  
  // 用于合并基础路径配置和接口单独配置
  private mergeConfig(options: AxiosRequestConfig): AxiosRequestConfig { 
    return Object.assign({ 
      baseURL: this.baseUrl,
      timeout: 2000,
    }, options);
  }
}

// 接口返回数据结构
export interface ResponseData {
  code: number;
  msg: string;
  data?: any;
}

// 返回 Axios 请求实例
export const http = new HttpRequest()